package com.lemon.exam.common.util;

import com.lemon.exam.common.entity.system.LoginUser;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * Security工具类，用来获取登录用户信息
 *
 * @author Lemon
 * @since 2025/3/25 12:13
 */
public final class SecurityUtil {

    //密码编码器
    private static final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    /**
     * 获取当前登录用户的认证信息
     *
     * @return
     */
    public static Mono<Authentication> getAuthentication() {
        return Mono.deferContextual(contextView -> ReactiveSecurityContextHolder.getContext()
                .mapNotNull(SecurityContext::getAuthentication)
                .contextWrite(contextView) // 保留上下文
        );
    }

    /**
     * 获取当前登录用户
     *
     * @return
     */
    public static Mono<LoginUser> getLoginUser() {
        return getAuthentication().mapNotNull(authentication -> {
                    Object principal = authentication.getPrincipal();
                    return principal instanceof LoginUser ? (LoginUser) principal : null;
                })
                .defaultIfEmpty(new LoginUser()); // 保证非空
    }

    /**
     * 获取当前登录用户的用户ID
     *
     * @return
     */
    public static Mono<Long> getUserId() {
        return getLoginUser().map(LoginUser::getId);
    }

    /**
     * 获取当前登录用户的用户名
     *
     * @return
     */
    public static Mono<String> getUsername() {
        return getLoginUser().map(LoginUser::getUsername);
    }

    /**
     * 获取当前登录用户的权限
     *
     * @return
     */
    public static Flux<GrantedAuthority> getAuthorities() {
        return getLoginUser().map(LoginUser::getAuthorities).flatMapMany(Flux::fromIterable);
    }

    /**
     * 获取当前登录用户的资源信息
     *
     * @return
     */
    public static Flux<String> getResourceList() {
        return getLoginUser().map(LoginUser::getResourceList).flatMapMany(Flux::fromIterable);
    }

    /**
     * 密码匹配
     *
     * @param password
     * @param encodedPassword
     * @return
     */
    public static boolean passwordMatch(String password, String encodedPassword) {
        return passwordEncoder.matches(password, encodedPassword);
    }

    /**
     * 密码加密
     *
     * @param password
     * @return
     */
    public static String passwordEncode(String password) {
        return passwordEncoder.encode(password);
    }
}
